package com.guli.gulimall.product.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.guli.gulimall.product.conf.MyRedissonConfig;
import com.guli.gulimall.product.dao.CategoryDao;
import com.guli.gulimall.product.vo.Catalog2Vo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.stereotype.Service;

import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.guli.common.utils.PageUtils;
import com.guli.common.utils.Query;


import com.guli.gulimall.product.entity.CategoryEntity;
import com.guli.gulimall.product.service.CategoryService;


@Service("categoryService")
public class CategoryServiceImpl extends ServiceImpl<CategoryDao, CategoryEntity> implements CategoryService {


    @Autowired
    MyRedissonConfig myRedissonConfig;


    @Autowired
    CategoryDao categoryDao;

    @Autowired
    StringRedisTemplate stringRedisTemplate;

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<CategoryEntity> page = this.page(
                new Query<CategoryEntity>().getPage(params),
                new QueryWrapper<CategoryEntity>()
        );

        return new PageUtils(page);
    }

    @Override
    public List<CategoryEntity> treelist() {

        List<CategoryEntity> selectList = categoryDao.selectList(null);

        List<CategoryEntity> list1 = selectList.stream().filter(item -> {

            return item.getParentCid().equals(0l);
        }).sorted((s1,s2)->{
            return (s1.getSort()!=null?s1.getSort():0)-(s2.getSort()!=null?s2.getSort():0);

        }).map(item -> {

            List<CategoryEntity> categoryEntities = find(selectList, item);

            item.setChildren(categoryEntities);
            return item;
        }).collect(Collectors.toList());


        return list1;
    }

    @Override
    public List<CategoryEntity> getCategotyLevelList() {


        QueryWrapper<CategoryEntity> w = new QueryWrapper<>();

        w.eq("parent_cid",0);

        return baseMapper.selectList(w);
    }


    public Map<String, List<Catalog2Vo>> findCatalog2() {

        List<CategoryEntity> categoryEntityList = baseMapper.selectList(null);

        //2、筛选所有的一级分类
        Map<String, List<Catalog2Vo>> map = categoryEntityList.stream().filter(item -> {
            return item.getParentCid().equals(0l);
        }).map(item -> {
            return item;
        }).collect(Collectors.toMap(k -> {
            return k.getCatId().toString();
        }, v -> {
            //v 所有的一级分类
            List<Catalog2Vo> l2List = categoryEntityList.stream().filter(item -> {
                return item.getParentCid().equals(v.getCatId());
            }).map(item -> {
                //item 就是二级分类
                Catalog2Vo catalog2Vo = new Catalog2Vo();
                catalog2Vo.setCatId(item.getCatId());
                catalog2Vo.setName(item.getName());
                catalog2Vo.setParentCid(item.getParentCid());
                //开始收集三级分类
                List<Catalog2Vo.Catalog3Vo> l3List = categoryEntityList.stream().filter(cata -> {
                    return cata.getParentCid().equals(item.getCatId());
                }).map(l3 -> {
                    Catalog2Vo.Catalog3Vo catalog3Vo = new Catalog2Vo.Catalog3Vo();
                    catalog3Vo.setId(l3.getCatId());
                    catalog3Vo.setName(l3.getName());
                    catalog3Vo.setParentCid(l3.getParentCid());
                    return catalog3Vo;
                }).collect(Collectors.toList());
                //赋值三级分类
                catalog2Vo.setCatalog3List(l3List);

                return catalog2Vo;
            }).collect(Collectors.toList());
            return l2List;
        }));
        return map;
    }
    @Override
    public Map<String, List<Catalog2Vo>> findCatalog() {

        String catalog = stringRedisTemplate.opsForValue().get("catalog");

        if (catalog==null){
            String replace = UUID.randomUUID().toString().replace("-", "");
            Boolean token = stringRedisTemplate.opsForValue().setIfAbsent("token", replace,30, TimeUnit.SECONDS);

            if (token){
                try {
                    System.out.println("数据库查询");
                    Map<String, List<Catalog2Vo>> catalog2 = findCatalog2();
                    stringRedisTemplate.opsForValue().set("catalog", JSON.toJSONString(catalog2));

                    return catalog2;
                }finally {
                    String script ="if redis.call(\"get\",KEYS[1]) == ARGV[1]\n" +
                            "then\n" +
                            "    return redis.call(\"del\",KEYS[1])\n" +
                            "else\n" +
                            "    return 0\n" +
                            "end";
                    stringRedisTemplate.execute(new DefaultRedisScript<Long>(script, Long.class), Arrays.asList("catalog"),replace);
                }
            }
        }

        Map<String, List<Catalog2Vo>> stringListMap = JSON.parseObject(catalog, new TypeReference<Map<String, List<Catalog2Vo>>>() {
        });
        System.out.println("命中redisi");

        return stringListMap;
    }


    private List<CategoryEntity> find(List<CategoryEntity> list,CategoryEntity list1){

        List<CategoryEntity> collect = list.stream().filter(item -> {


            return item.getParentCid().equals(list1.getCatId());
        }).sorted((s1,s2)->{

            return (s1.getSort()!=null?s1.getSort():0)-(s2.getSort()!=null?s2.getSort():0);

        }).map(item -> {

            List<CategoryEntity> c = find(list, item);
            item.setChildren(c);
            return item;
        }).collect(Collectors.toList());
        return collect;
    }



}